/**
 * Copyright (c) 2006 RiseSoft Co.,Ltd  
 * $Header$
 */
package net.risesoft.risebi.collection.service.impl;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.risesoft.risebi.collection.commons.constants.SystemConstants;
import net.risesoft.risebi.collection.dao.DataOperationDao;
import net.risesoft.risebi.collection.dao.ReportInstanceR6Dao;
import net.risesoft.risebi.collection.event.eventobj.DataLogEventObj;
import net.risesoft.risebi.collection.event.eventobj.EventObject;
import net.risesoft.risebi.collection.formula.runtime.Auditor;
import net.risesoft.risebi.collection.groovy.Fault;
import net.risesoft.risebi.collection.model.Catalog;
import net.risesoft.risebi.collection.model.RangeObj;
import net.risesoft.risebi.collection.model.ReportData;
import net.risesoft.risebi.collection.model.ReportDataR6;
import net.risesoft.risebi.collection.model.ReportInstance;
import net.risesoft.risebi.collection.model.ReportInstanceR6;
import net.risesoft.risebi.collection.model.RowObj;
import net.risesoft.risebi.collection.model.Template;
import net.risesoft.risebi.collection.model.TemplateIndication;
import net.risesoft.risebi.collection.model.TemplateRange;
import net.risesoft.risebi.collection.model.User;
import net.risesoft.risebi.collection.service.AuditFaultManager;
import net.risesoft.risebi.collection.service.DataOperationManager;
import net.risesoft.risebi.collection.service.DataOperationManagerR6;
import net.risesoft.risebi.collection.service.DynaBeanManager;
import net.risesoft.risebi.collection.service.ReportInstanceFileManager;
import net.risesoft.risebi.collection.service.ReportInstanceLevelStatusManager;
import net.risesoft.risebi.collection.service.ReportInstanceManager;
import net.risesoft.risebi.collection.service.ReportInstanceManagerR6;
import net.risesoft.risebi.collection.service.ReportInstanceOperationManager;
import net.risesoft.risebi.collection.service.TemplateIndicationManager;
import net.risesoft.risebi.collection.service.TemplateManager;
import net.risesoft.risebi.collection.validator.ValidatorManager;
import net.risesoft.risebi.collection.web.BaseAction;
import net.risesoft.risebi.commons.hibernateextension.HibernateUtil;
import net.risesoft.risebi.commons.util.ContextUtil;
import net.risesoft.risebi.commons.util.GUID;

import org.appfuse.dao.Dao;
import org.appfuse.service.impl.BaseManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author <a href="mailto: baiyibing@gmail.com">王锤</a>
 * @version $Revision$
 * 
 */
@Repository(value = "dataOperationManagerR6")
@SuppressWarnings({ "unchecked", "rawtypes" })
public class DataOperationManagerR6Impl extends DataOperationManagerImpl implements DataOperationManagerR6 {
	
	private ReportInstanceR6Dao reportInstanceR6Dao;

    public ReportInstanceR6Dao getReportInstanceR6Dao() {
		return reportInstanceR6Dao;
	}
    @Autowired
	public void setReportInstanceR6Dao(ReportInstanceR6Dao reportInstanceR6Dao) {
		this.reportInstanceR6Dao = reportInstanceR6Dao;
	}



	@Override
	public ReportData getR6ReportData(String reportTaskID,ReportInstance ri, String templateGuid)
			throws Exception {
		// TODO Auto-generated method stub
		Template template = (Template) this.getTemplateManager().getObject(Template.class, templateGuid);
        List<TemplateIndication> templateIndications = template.getTemplateIndications();
        List<TemplateRange> templateRanges = template.getTemplateRanges();

        Map<String, TemplateIndication> templateIndicationsMap = new HashMap<String, TemplateIndication>();
        for (int i = 0; i < templateIndications.size(); i++) {
            TemplateIndication ti = templateIndications.get(i);
            templateIndicationsMap.put(ti.getAlias_Name(), ti);
        }

        Map<String, TemplateIndication> columnTemplateIndicationMap = new HashMap<String, TemplateIndication>();
        for (int i = 0; i < templateIndications.size(); i++) {
            TemplateIndication ti = templateIndications.get(i);
            String columnName = ti.getColumnName();
            if (columnName != null)
                columnName = columnName.toLowerCase();
            columnTemplateIndicationMap.put(columnName, ti);
        }

        ReportData rd = new ReportData();
        Map<String, String> indis = this.getIndicationData(reportTaskID,ri.getGuid(), templateIndications);
        rd.setIndis(indis);

        Map<String, RangeObj> ranges = this.getRangeData(reportTaskID,ri.getGuid(), templateGuid, templateRanges, templateIndicationsMap, false);
        rd.setRanges(ranges);

        return rd;
	}
	
	 private Map<String, String> getIndicationData(String reportTaskID,String reportInstanceGuid, List<TemplateIndication> templateIndications) throws Exception {
	        Map<String, String> returnedMap = new HashMap<String, String>();
	        List<String> tableNames = new ArrayList<String>();

	        for (TemplateIndication ti : templateIndications) {
	            String tableName = ti.getTableName();
	            if (tableName.indexOf("dyna_data_") > -1 && !tableNames.contains(tableName)) {
	                tableNames.add(tableName);
	            }
	        }

	        for (String tableName : tableNames) {
	            String hqlFields = "";
	            List<String> columnNames = new ArrayList<String>();
	            HashMap<String, String> column2Alias = new HashMap<String, String>();

	            for (TemplateIndication ti : templateIndications) {
	                if (tableName.equalsIgnoreCase(ti.getTableName())) {
	                    String columnName = ti.getColumnName().trim();
	                    columnNames.add(columnName);
	                    column2Alias.put(columnName, ti.getAlias_Name());
	                    if (hqlFields.length() == 0) {
	                        hqlFields = columnName + " as " + columnName;
	                    } else {
	                        hqlFields += "," + columnName + " as " + columnName;
	                    }
	                }
	            }

	            //List<HashMap<String, Object>> list = this.find("from " + tableName + " as t where t.reportinstance_guid='" + reportInstanceGuid + "'");
	            
	            List<ReportDataR6> list = this.getReportInstanceR6Dao().getReportDatas(reportTaskID, reportInstanceGuid, "indis");
	            
            	for (ReportDataR6 r6 : list) {
            		returnedMap.put(r6.getRowCode(), r6.getValueStr());
            	}
	            // List<HashMap<String,Object>> list = this.find("select new map(" +
	            // hqlFields + ") from " + tableName +
	            // " as t where t.reportinstance_guid='" + reportInstanceGuid +
	            // "'");
	            /*
            	if (list.size() > 0) {
	                HashMap<String, Object> map = list.get(0);
	                for (String columnName : columnNames) {
	                    Object columnValue = map.get(columnName.toLowerCase());
	                    String value = null;
	                    if (columnValue != null) {
	                        if ((columnValue instanceof Double) || (columnValue instanceof Float)) {
	                            value = String.format("%.2f", columnValue);
	                            if (value.endsWith(".00")) {
	                                // 表示没有小数点
	                                value = value.substring(0, value.length() - 3);
	                            }
	                        } else {
	                            value = columnValue.toString();
	                        }
	                    }

	                    String aliasName = column2Alias.get(columnName);
	                    returnedMap.put(aliasName, value);
	                }
	            }
	            */
	        }

	        returnedMap.put("reportinstance_guid", reportInstanceGuid);
	        return returnedMap;
	    }

	 private Map<String, RangeObj> getRangeData(String reportTaskID,String reportInstanceGuid, String templateGuid, List<TemplateRange> templateRanges, Map<String, TemplateIndication> templateIndicationsMap, boolean pure) throws Exception {
	        Map<String, RangeObj> returnedMap = new HashMap<String, RangeObj>();
	        //如果模板中没有range则返回，有一些表只定义了IndicationData，只有dyna_data_表，无dyna_dataset
	        if (templateRanges.isEmpty())
	            return returnedMap;

	        Map<String, String> tableNameMap = new HashMap<String, String>();

	        boolean found = false;

	        if (templateRanges.size() > 1) {
	            for (int i = 0; i < templateRanges.size(); i++) {
	                TemplateRange templateRange = templateRanges.get(i);
	                //templateRange包含的代码列的值，对应数据库横表的业务主键，即行定义
	                String containedCodes = templateRange.getContainedCodes();
	                if (containedCodes != null) {
	                    String[] strContainedCodesColl = containedCodes.split(",");
	                    List<String> containedCodeList = Arrays.asList(strContainedCodesColl);
	                    //将代码列字符串分解为List<String>，设置到templateRange。
	                    templateRange.setContainedCodeList(containedCodeList);
	                }
	            }
	        }

	        for (int i = 0; i < templateRanges.size(); i++) {
	            found = false;

	            TemplateRange tr = templateRanges.get(i);
	          //templateRange包含的指标列的值，对应数据库横表的其他列,即列定义
	            //[daima, field1, field2, field3, field4, field5, field6, field7]
	            String containedIndications = tr.getIncludedAlias();
	            String[] containedIndicationColl = containedIndications.split(",");
	            String tableName = null;
	            for (int j = 0; j < containedIndicationColl.length; j++) {
	                String containedIndicationName = containedIndicationColl[j];
	                TemplateIndication ti = templateIndicationsMap.get(containedIndicationName);
	                tableName = ti.getTableName();

	                Object o = tableNameMap.get(tableName);
	                if (o == null) {
	                    tableNameMap.put(tableName, "0");
	                    found = true;
	                }

	                break;
	            }
	            //如果为某个指标找到了对应的数据库表
	            if (found) {
	                // 组建每个range中对应的catalogName
	                Map<String, String> rangeCatalogNameMap = this.makeRangeCatalogName(templateGuid);

	                String rangeName = tr.getName();
	                String catalogName = rangeCatalogNameMap.get(rangeName);
	                TemplateIndication tiCatalog = templateIndicationsMap.get(catalogName);
	                String catalogColumnName = tiCatalog.getColumnName().toLowerCase();

	                
	                //List list = new ArrayList();
	                //if ("CA68830FFFFFFFFFC14F229A000004EE".equals(templateGuid)) { // 附表6-2省级集中招标采购的药品目录清单
	                //    list = this.find("from " + tableName + " as t where t.reportinstance_guid='" + reportInstanceGuid + "' order by t." + catalogColumnName, 0, 10);
	                //} else {
	                //    list = this.find("from " + tableName + " as t where t.reportinstance_guid='" + reportInstanceGuid + "' order by t." + catalogColumnName);
	                //}
	                
	                List<ReportDataR6> list = this.getReportInstanceR6Dao().getReportDatas(reportTaskID, reportInstanceGuid, rangeName);
	                for (ReportDataR6 r6 : list) {
	                	Object catalogCode = r6.getRowCode();//'H001'实际上就是行代码
	                	
	                	// 模板中内含range 2个以上时，要根据内含的catalogCodes来区分数据是属于哪个range，对应的结果保存在rangeName中
	                    if (templateRanges.size() > 1) {
	                        for (int k = 0; k < templateRanges.size(); k++) {
	                            TemplateRange templateRange = templateRanges.get(k);
	                            List<String> containedCodeList = templateRange.getContainedCodeList();
	                            if (containedCodeList == null)
	                                continue;
	                            if (containedCodeList.contains(catalogCode.toString())) {
	                                if (templateRange.getName().equals(rangeName))
	                                    break;

	                                rangeName = templateRange.getName();
	                                break;
	                            }
	                        }
	                    }
	                	
	                	RangeObj range = returnedMap.get(rangeName);
                        if (range == null) {
                            range = new RangeObj();
                            returnedMap.put(rangeName, range);
                        }

                        Map<String, RowObj> rows = range.getRows();
                        if (rows == null) {
                            rows = new HashMap<String, RowObj>();
                            range.setRows(rows);
                        }
                        //行是用catalogCode作为主键，所谓业务主键
                        RowObj row = rows.get(catalogCode.toString());

                        if (row == null) {
                            row = new RowObj();
                            rows.put(catalogCode.toString(), row);
                        }

                        Map<String, String> cols = row.getCols();
                        if (cols == null) {
                            cols = new HashMap<String, String>();
                            row.setCols(cols);
                        }
                        if (pure) {
                            cols.put(r6.getColCode(), r6.getValueStr());                            
                            //cols.put(containedIndicationName, value);
                        } else {
                            cols.put(r6.getColCode(),  r6.getValueStr());
                        }
                        
	                    //String item_guid = (String) map.get("item_guid");//range对应表中的物理主键
                        //竖表没有对应的item_guid，先造一个吧。
                        //已经填报的表，每行有item_guid
                        //<td  align='center' valign='middle' class='sAC100142000000005E43DB0D0000009E'>
                        //<input type="hidden" name="rd.ranges['range1'].rows['H001'].cols['1']" value="H001" id="rd.ranges['range1'].rows['H001'].cols['1']"/>
                        //<input type="hidden" name="rd.ranges['range1'].rows['H001'].cols['item_guid']" value="AC10014200000000204AF28D00000107" id="rd.ranges['range1'].rows['H001'].cols['item_guid']"/>
                        //H001</td>
                        //已经填报的表，行上无有item_guid
                        //<td  align='center' valign='middle' class='sAC100142000000005E43DAFD00000095'>
                        //<input type="hidden" name="rd.ranges['range1'].rows['H001'].cols['1']" value="H001" id="rd.ranges['range1'].rows['H001'].cols['1']"/>
                        //H001</td>
                        String item_guid = r6.getRowNo();
	                    returnedMap.get(rangeName).getRows().get(catalogCode.toString()).getCols().put("item_guid", item_guid);
	                }
	                
	                /*
	                //同一个物理表tableName可能对应多个同结构的range
	                for (int j = 0; j < list.size(); j++) {
	                    Map map = (Map) list.get(j);
	                    Object catalogCode = map.get(catalogColumnName);//'H001'实际上就是行代码

	                    // 模板中内含range 2个以上时，要根据内含的catalogCodes来区分数据是属于哪个range，对应的结果保存在rangeName中
	                    if (templateRanges.size() > 1) {
	                        for (int k = 0; k < templateRanges.size(); k++) {
	                            TemplateRange templateRange = templateRanges.get(k);
	                            List<String> containedCodeList = templateRange.getContainedCodeList();
	                            if (containedCodeList == null)
	                                continue;
	                            if (containedCodeList.contains(catalogCode.toString())) {
	                                if (templateRange.getName().equals(rangeName))
	                                    break;

	                                rangeName = templateRange.getName();
	                                break;
	                            }
	                        }
	                    }
	                    //rd.ranges['range1'].rows['H001'].cols['7']
	                    //rangename='range1'
	                    //catalogCode='H001'实际上就是行代码
	                    //columnCode='7'
	                    //rd.indis['shequ']
	                    //自由项的别名aliasname='shequ'
	                    for (int k = 0; k < containedIndicationColl.length; k++) {
	                        String containedIndicationName = containedIndicationColl[k];
	                        //containedIndicationName=daima 对应excel某个CELL的别名
	                        TemplateIndication ti = templateIndicationsMap.get(containedIndicationName);
	                        String columnCode = ti.getAlias_ColumnCode();//columnCode =甲or乙or 丙 excel表上的列代码

	                        String realColumnName = ti.getColumnName().toLowerCase();//数据库列名 filed1
	                        Object columnValue = map.get(realColumnName);
	                        String value = null;
	                        if (columnValue == null) {
	                            continue;
	                            // value = "";
	                        } else {
	                            if ((columnValue instanceof Double) || (columnValue instanceof Float)) {
	                                value = String.format("%.2f", columnValue);
	                                if (value.endsWith(".00")) {
	                                    // 表示没有小数点
	                                    value = value.substring(0, value.length() - 3);
	                                }
	                            } else {
	                                value = columnValue.toString();
	                            }
	                        }

	                        RangeObj range = returnedMap.get(rangeName);
	                        if (range == null) {
	                            range = new RangeObj();
	                            returnedMap.put(rangeName, range);
	                        }

	                        Map<String, RowObj> rows = range.getRows();
	                        if (rows == null) {
	                            rows = new HashMap<String, RowObj>();
	                            range.setRows(rows);
	                        }
	                        //行是用catalogCode作为主键，所谓业务主键
	                        RowObj row = rows.get(catalogCode.toString());

	                        if (row == null) {
	                            row = new RowObj();
	                            rows.put(catalogCode.toString(), row);
	                        }

	                        Map<String, String> cols = row.getCols();
	                        if (cols == null) {
	                            cols = new HashMap<String, String>();
	                            row.setCols(cols);
	                        }

	                        if (pure) {
	                            cols.put(containedIndicationName, value);
	                        } else {
	                            cols.put(columnCode, value);
	                        }
	                    }

	                    String item_guid = (String) map.get("item_guid");//range对应表中的物理主键
	                    returnedMap.get(rangeName).getRows().get(catalogCode.toString()).getCols().put("item_guid", item_guid);
	                }
	                */
	            }
	        }

	        return returnedMap;
	    }


	private void saveIndication(String reportTaskID,ReportInstance ri,
			ReportData rd, String templateGuid,
			List<TemplateIndication> templateIndications,
			Map<String, TemplateIndication> templateIndicationsMap,
			boolean fromImp, boolean needSkip, ReportData beforeReportData,
			ReportData afterReportData) throws Exception {
		Map<String, String> indis = rd.getIndis();
		if (indis == null || indis.isEmpty()) {
			return;
		}
		//String reportTaskID = ri.getApplication().getGuid();
		String reportInstanceGuid = ri.getGuid();

		List<String> tableNames = new ArrayList<String>();
		for (TemplateIndication ti : templateIndications) {
			String tableName = ti.getTableName();
			if (tableName.indexOf("dyna_data_") > -1
					&& !tableNames.contains(tableName)) {
				tableNames.add(tableName);
			}
		}

		if (tableNames.isEmpty()) {
			throw new Exception("没有对模板定义好数据库字段影射关系");
		}
		List<ReportDataR6> r6list = new ArrayList<ReportDataR6>();
		Map<String, Map> savedMapOfTables = new HashMap<String, Map>();
		Map<String, Boolean> editOfTables = new HashMap<String, Boolean>();
		for (String tableName : tableNames) {
			Map<String, String> savedMap = new HashMap<String, String>();
			for (TemplateIndication ti : templateIndications) {
				if (tableName.equalsIgnoreCase(ti.getTableName())) {
					String columnName = ti.getColumnName();
					String aliasName = ti.getAlias_Name();
					String aliasValue = indis.get(aliasName);
					savedMap.put(columnName.toLowerCase(), aliasValue);
					ReportDataR6 r6 = new ReportDataR6();
					r6.setReportID(reportInstanceGuid);
					r6.setColCode("1");
					r6.setRowCode(aliasName);
					r6.setRangeCode("indis");
					r6.setValueStr(aliasValue);
					r6list.add(r6);
				}
			}
		}
		// {jsbr=null, tbdw=null, tabindex=null, $type$=dyna_data_jsbrd,
		// tbrq=null, tbr=null,
		// reportinstance_guid=AC100142000000000060E0510000016D}
		if (!this.getReportInstanceR6Dao().hasReportDatas(reportTaskID, reportInstanceGuid)) {
			// 没有则新增
			//savedMap.put("reportinstance_guid", reportInstanceGuid);
			//editOfTables.put(tableName, false);
		} else {
			// 还需要从数据库再取一遍，为了保存修改轨迹
			Map beforeMap = this.getIndicationData(reportTaskID,
					reportInstanceGuid, templateIndications);
			beforeReportData.setIndis(beforeMap);
		}
		this.getReportInstanceR6Dao().saveReportDatas(reportTaskID, reportInstanceGuid, r6list);
		boolean afterReportDataNeed = true;
		// 还需要从数据库再取一遍，为了保存修改轨迹
		if (afterReportDataNeed) {
			Map afterMap = this.getIndicationData(reportTaskID,
					reportInstanceGuid, templateIndications);
			afterReportData.setIndis(afterMap);
		}
	}
	
    @SuppressWarnings("rawtypes")
    private void saveRange(String reportTaskID,ReportInstance ri, ReportData rd, String templateGuid, Map<String, Map<String, String>> rangeColumnCodeMap, boolean fromImp, boolean needSkip, Map<String, TemplateRange> templateRangeMap, List<TemplateRange> templateRangeList, Map<String, TemplateIndication> templateIndicationMap, ReportData beforeReportData, ReportData afterReportData) throws Exception {
        Map<String, List<Map<String, String>>> savedMap = new HashMap<String, List<Map<String, String>>>();
        Map<String, RangeObj> ranges = rd.getRanges();
        if (ranges == null)
            return;
        Iterator<String> rangesIt = ranges.keySet().iterator();
        //String reportTaskID = ri.getApplication().getGuid();
        String reportInstanceGuid = ri.getGuid();

        // 还需要先从数据库取一遍，为了保存修改轨迹
        try {
            Map beforeMap = this.getRangeData(reportTaskID,ri.getGuid(), templateGuid, templateRangeList, templateIndicationMap, true);
            beforeReportData.setRanges(beforeMap);
        } catch (Exception e) {
            // ignore
        }
        List<ReportDataR6> r6list = new ArrayList<ReportDataR6>();
        while (rangesIt.hasNext()) {
            String rangeName = rangesIt.next();
            Map<String, String> columnCodeMap = rangeColumnCodeMap.get(rangeName);
            //{3=dyna_dataset_jsbrd_range1###field2, 2=dyna_dataset_jsbrd_range1###field1, 10=dyna_dataset_jsbrd_range1###field6, 1=dyna_dataset_jsbrd_range1###DAIMA, 6=dyna_dataset_jsbrd_range1###field4, 4=dyna_dataset_jsbrd_range1###field3, 8=dyna_dataset_jsbrd_range1###field5, 11=dyna_dataset_jsbrd_range1###field7}
            TemplateRange templateRange = templateRangeMap.get(rangeName);
            String catalogCodeColumnCode = templateRange.getCatalogCodeColumnCode();
            String catalogCodetableColumn = columnCodeMap.get(catalogCodeColumnCode);
            String[] catalogCodetableColumnColl = catalogCodetableColumn.split("###");
            String catalogCodeColumn = catalogCodetableColumnColl[1].trim().toLowerCase();
            
            RangeObj range = ranges.get(rangeName);
            Map<String, RowObj> rows = range.getRows();
            Iterator<String> rowIt = rows.keySet().iterator();
            
            Map<String, String> rowNoMap = new HashMap<String, String>();
            String tableName = null;
            while (rowIt.hasNext()) {
                String rowCatalogCode = rowIt.next();
                RowObj row = rows.get(rowCatalogCode);
                Map<String, String> cols = row.getCols();
                //{3=, 2=, 10=, 1=H013, 6=, 4=, 8=, 11=}
                String columnName = null;
                Iterator<String> colIt = cols.keySet().iterator();
                while (colIt.hasNext()) {
                    String columnCode = colIt.next();//3
                    String tableColumn = columnCodeMap.get(columnCode);
                    //dyna_dataset_jsbrd_range1###field2
                    if (tableColumn == null) {
                    	//innerSavedMap.put(columnCode, cols.get(columnCode));
                        continue;
                    }

                    String[] tableColumnColl = tableColumn.split("###");

                    tableName = tableColumnColl[0].toLowerCase();//dyna_dataset_jsbrd_range1
                    columnName = tableColumnColl[1].toLowerCase();//field2

                    //需要保存到数据库中的数据库列和值的对应关系
                    //innerSavedMap.put(columnName, cols.get(columnCode));
                    
                    String itemGuid =  cols.get("item_guid"); 
                    if (itemGuid == null) {
                    	String vItemGuid = rowNoMap.get(rowCatalogCode);
                    	itemGuid = this.getItemGuid(reportTaskID, reportInstanceGuid, rangeName, rowCatalogCode, vItemGuid, fromImp, needSkip);
                    	rowNoMap.put(rowCatalogCode, itemGuid);
                    }                    
					ReportDataR6 r6 = new ReportDataR6();
					r6.setReportID(reportInstanceGuid);
					r6.setColCode(columnCode);
					r6.setRowCode(rowCatalogCode);
					r6.setRangeCode(rangeName);
					r6.setValueStr(cols.get(columnCode));
					r6.setRowNo(itemGuid);
					r6list.add(r6);
                }           
            }

            // 假如是二维增一或者不定长表，则在保存数据前需要删除原先的数据
            if (templateRange.getRangeType() == TemplateRange.RANGETYPE_ERWEIZENGYI || templateRange.getRangeType() == TemplateRange.RANGETYPE_TOPTOBOTTOM) {
            	if(this.getReportInstanceR6Dao().hasRangeDatas(reportTaskID, reportInstanceGuid, rangeName)){
            		this.getReportInstanceR6Dao().removeRangeDatas(reportTaskID, reportInstanceGuid, rangeName);
            	}
            }
        }

        //this.saveRangeData(savedMap);
        this.getReportInstanceR6Dao().saveReportDatas(reportTaskID, reportInstanceGuid, r6list);

        // 还需要从数据库再取一遍，为了保存修改轨迹
        try {
            Map afterMap = this.getRangeData(reportTaskID,reportInstanceGuid, templateGuid, templateRangeList, templateIndicationMap, true);
            afterReportData.setRanges(afterMap);
        } catch (Exception e) {
            // ignore
        }
    }
    
    private String getItemGuid(String reportTaskID,String reportInstanceGuid,String rangeName,String rowCatalogCode,String vItemGuid,boolean  fromImp,boolean needSkip){        
        //innerSavedMap.put("tabindex", "100.00");
        //innerSavedMap.put("reportinstance_guid", reportInstanceGuid);   
    	String itemGuid = vItemGuid;
        if (!fromImp) {
            if(itemGuid==null || itemGuid.trim().length()==0){
                //List list = this.find("from " + tableName + " as t where t.reportinstance_guid='" + reportInstanceGuid + "' and t." + catalogCodeColumn + "='" + catalogCode + "'");
            	ReportDataR6 loadedr6 = this.getReportInstanceR6Dao().getReportData(reportTaskID, reportInstanceGuid, rangeName,rowCatalogCode);
            	if (loadedr6==null) {
                    // reportinstance_guid和代码列唯一确定一行， 没有则新增
            		itemGuid = new GUID().toString();
                }else{
                	itemGuid = loadedr6.getRowNo();
                }
            }
        } else { //数据导入，应该没有item_guid
            //List list = this.find("from " + tableName + " as t where t.reportinstance_guid='" + reportInstanceGuid + "' and t." + catalogCodeColumn + "='" + catalogCode + "'");
        	ReportDataR6 loadedr6 = this.getReportInstanceR6Dao().getReportData(reportTaskID, reportInstanceGuid, rangeName,rowCatalogCode);
            if (needSkip) {
                if (loadedr6!=null) {
                    // 有则跳过
                } else {
                    // 没有则新增
                	itemGuid = new GUID().toString();
                }
            } else {
                if (loadedr6!=null) {
                    // 有则覆盖
//                    Map loadedMap = (Map) list.get(list.size()-1);
//                    loadedMap.remove("$type$");
//                    Iterator<String> innerSavedMapIterator = innerSavedMap.keySet().iterator();
//                    while (innerSavedMapIterator.hasNext()) {
//                        columnName = innerSavedMapIterator.next();
//                        if(!"item_guid".equalsIgnoreCase(columnName)){
//                            loadedMap.put(columnName, innerSavedMap.get(columnName));
//                        }
//                    }
//                    innerSavedMap = loadedMap;
//                    savedList.add(innerSavedMap);
                } else {
                    // 没有则新增
                	itemGuid = new GUID().toString();
                }
            }
        }
        return itemGuid;
    }
	@Override
	public Map addR6ReportData(String reportTaskID,
			String clientJsValidationError, ReportInstance ri, ReportData rd, String templateGuid, User user) throws Exception{
		// 建立map提高速度
        Template t = (Template) this.getTemplateManager().getObject(Template.class, templateGuid);
        List<TemplateIndication> templateIndicationList = t.getTemplateIndications();

        Map<String, TemplateIndication> templateIndicationMap = new HashMap<String, TemplateIndication>();
        for (int i = 0; i < templateIndicationList.size(); i++) {
            TemplateIndication ti = templateIndicationList.get(i);
            templateIndicationMap.put(ti.getAlias_Name(), ti);
        }

        // 组成列代码
        Map<String, Map<String, String>> rangeColumnCodeMap = new HashMap<String, Map<String, String>>();
        List<TemplateRange> templateRangeList = t.getTemplateRanges();
        Map<String, TemplateRange> templateRangeMap = new HashMap<String, TemplateRange>();
        for (int i = 0; i < templateRangeList.size(); i++) {
            TemplateRange templateRange = templateRangeList.get(i);
            templateRangeMap.put(templateRange.getName(), templateRange);
            Map<String, String> columnCodeMap = new HashMap<String, String>();
            rangeColumnCodeMap.put(templateRange.getName(), columnCodeMap);
            String includedAlias = templateRange.getIncludedAlias();
            String[] includedAliasColl = includedAlias.split(",");            
            for (int j = 0; j < includedAliasColl.length; j++) {
                String aliasName = includedAliasColl[j];
                TemplateIndication templateIndication = templateIndicationMap.get(aliasName);
                String catalogGuid = templateIndication.getRelated_Catalog_GUID();
                if(catalogGuid!=null&&!catalogGuid.equals("")){
                    templateRange.setCatalogCodeColumnCode(templateIndication.getAlias_ColumnCode());
                }
                columnCodeMap.put(templateIndication.getAlias_ColumnCode(), templateIndication.getTableName() + "###" + templateIndication.getColumnName());
            }
        }

        return this.addReportData(reportTaskID,clientJsValidationError, ri, rd, templateGuid, templateIndicationList, templateIndicationMap, rangeColumnCodeMap, user, true, true, true, false, false, templateRangeMap, templateRangeList);
    }
	
	public Map addReportData(String reportTaskID,String clientJsValidationError, ReportInstance ri, ReportData rd, String templateGuid, List<TemplateIndication> templateIndicationList, Map<String, TemplateIndication> templateIndicationMap, Map<String, Map<String, String>> rangeColumnCodeMap, User user, boolean needValidate, boolean needAudit, boolean needSendMessage, boolean fromImp, boolean needSkip, Map<String, TemplateRange> templateRangeMap, List<TemplateRange> templateRangeList) throws Exception {
        Map returnedMap = new HashMap();

        List<Fault> containedFaults = null;
        // 验证数据格式是否正确
        if (needValidate) {
            containedFaults = this.getValidatorManager().validate(0, templateGuid, rd);
            if (!containedFaults.isEmpty()) {
                returnedMap.put("containedFaults", containedFaults);
                returnedMap.put("validate", "0");
                return returnedMap;
            }
        }

        Map<String, List<Fault>> containedFaultMap = null;
        // 业务审核
        if (needAudit) {
            boolean hasQiangzhixingFault = false;
            containedFaultMap = this.getAuditor().doAudit(templateGuid, ri, rd, user);
            Iterator<String> it = containedFaultMap.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                String[] keyColl = key.split("###");
                if (keyColl[1].equals("1")) {
                    hasQiangzhixingFault = true;
                    break;
                }
            }

            if (hasQiangzhixingFault) {
                containedFaults = new ArrayList<Fault>();
                Iterator<Entry<String, List<Fault>>> entryIt = containedFaultMap.entrySet().iterator();
                while (entryIt.hasNext()) {
                    List<Fault> faultList = entryIt.next().getValue();
                    containedFaults.addAll(faultList);
                }
                returnedMap.put("containedFaults", containedFaults);
                returnedMap.put("audit", "0");
                return returnedMap;
            }
        }

        ReportData beforeReportData = new ReportData();
        ReportData afterReportData = new ReportData();

        // 保存
        this.saveData(reportTaskID,clientJsValidationError, ri, rd, templateGuid, containedFaultMap, templateIndicationList, templateIndicationMap, rangeColumnCodeMap, user, fromImp, needSkip, templateRangeMap, templateRangeList, beforeReportData, afterReportData);

        // 没有强制性审核错误，只有一般性审核错误，保存非强制性审核错误
        if (needSendMessage) {
            if (!containedFaultMap.isEmpty()) {
                containedFaults = new ArrayList<Fault>();

                for (Map.Entry<String, List<Fault>> entry : containedFaultMap.entrySet()) {
                    String key = entry.getKey();
                    String[] keyColl = key.split("###");
                    if (keyColl[1].equals("1"))
                        continue;

                    List<Fault> faultList = entry.getValue();
                    containedFaults.addAll(faultList);
                }

                this.getAuditFaultManager().saveAuditFault(ri.getGuid(), containedFaults);
            }
        }

        // 发送新增、修改数据日志（异步事件）
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("targetGuid", ri.getGuid());
        dataMap.put("beforeReportData", beforeReportData);
        dataMap.put("afterReportData", afterReportData);
        dataMap.put("user", user);
        dataMap.put("baseInfo", false);
        EventObject dataLogEventObject = new DataLogEventObj(this);
        dataLogEventObject.setDataMap(dataMap);
        ContextUtil.getAc().publishEvent(dataLogEventObject);

        returnedMap.put("returnString", BaseAction.ADD);

        return returnedMap;
    }
	
    @Transactional(rollbackFor = { java.lang.Exception.class })
    private void saveData(String reportTaskID,String clientJsValidationError, ReportInstance ri, ReportData rd, String templateGuid, Map<String, List<Fault>> containedFaultMap, List<TemplateIndication> templateIndicationList, Map<String, TemplateIndication> templateIndicationMap, Map<String, Map<String, String>> rangeColumnCodeMap, User user, boolean fromImp, boolean needSkip, Map<String, TemplateRange> templateRangeMap, List<TemplateRange> templateRangeList, ReportData beforeReportData, ReportData afterReportData) throws Exception {
        // 保存游离项
        this.saveIndication(reportTaskID,ri, rd, templateGuid, templateIndicationList, templateIndicationMap, fromImp, needSkip, beforeReportData, afterReportData);

        // saveRange
        if ("CA68830FFFFFFFFFC14F229A000004EE".equals(templateGuid)) {} else {
            if (templateRangeList != null && !templateRangeList.isEmpty()) {
                this.saveRange(reportTaskID,ri, rd, templateGuid, rangeColumnCodeMap, fromImp, needSkip, templateRangeMap, templateRangeList, templateIndicationMap, beforeReportData, afterReportData);
            }
        }

        // 没有强制性审核错误，只有一般性审核错误，则修改reportInstance状态为：审核未通过，否则状态为通过
        ReportInstanceR6 r6 =  this.getReportInstanceR6Dao().getObject(reportTaskID,ri.getGuid());
        //ReportInstance reportInstance = (ReportInstance) reportInstanceManager.getObject(ReportInstance.class, ri.getGuid());
        if (containedFaultMap != null && !containedFaultMap.isEmpty()) {
            //reportInstance.setStatus(ReportInstance.STATUS_HASNORMALERROR);
        } else {
            //reportInstance.setStatus(ReportInstance.STATUS_YES);
        }

        if (clientJsValidationError.equals("true")) {
            //reportInstance.setStatus(ReportInstance.STATUS_HASNORMALERROR);
        }
        
        // 修改更新时间
        // 1：新增 2：修改 3：删除
        int operateType = 2;
        Map<String, String> beforeIndis = beforeReportData.getIndis();
        if (beforeIndis == null) {
            // 表明这是新增
            operateType = 1;
        }
        if (operateType == 1) {
            //reportInstance.setFirstUploadDate(new Date());
            r6.setFirstDate(new Timestamp(new Date().getTime()));
        }
        //reportInstance.setLastModifiedDate(new Date());
        r6.setCurrentDate(new Timestamp(new Date().getTime()));
       
        //reportInstanceManager.saveObject(reportInstance);
        this.getReportInstanceR6Dao().saveObject(r6);
    }
}